import type { HttpError, HttpInterceptorManager, HttpRequestConfig, HttpResponse, HttpTask } from '../luch-request'
import Request from '../luch-request'

import RequestInterceptorsManager from './request-interceptors-manager'

class BaseRequest {
  service: Request
  interceptors: { request: HttpInterceptorManager<HttpRequestConfig>, response: HttpInterceptorManager<HttpResponse, HttpError> }
  requestInterceptorsManager!: RequestInterceptorsManager<HttpRequestConfig<HttpTask>, HttpResponse<any, HttpTask>, HttpError<any, HttpTask>>
  constructor(arg?: HttpRequestConfig) {
    this.service = new Request(arg)
    this.interceptors = this.service.interceptors
    this.registerInterceptors()
  }

  setConfig(config: (config: HttpRequestConfig<HttpTask>) => HttpRequestConfig<HttpTask>) {
    this.service.setConfig(config)
  }

  registerInterceptors() {
    const requestInterceptorsManager = this.requestInterceptorsManager = new RequestInterceptorsManager<HttpRequestConfig<HttpTask>, HttpResponse<any, HttpTask>, HttpError<any, HttpTask>>()

    this.interceptors.request.use(async config => {
      try {
        const resConfig = await requestInterceptorsManager.registerRequestSuccess(config)
        if (resConfig?.custom!.__SKIP_FETCH__) return Promise.reject(resConfig)
        return resConfig
      }
      catch (e) {
        return Promise.reject(e)
      }
    }, config => Promise.reject(config))

    this.interceptors.response.use(response => requestInterceptorsManager.registerResponseSuccess(response) as any, async err => {
      if ((err as HttpRequestConfig<HttpTask>)?.custom?.__SKIP_FETCH__) return requestInterceptorsManager.registerResponseSuccess(err as HttpResponse)
      return Promise.reject(await requestInterceptorsManager.registerResponseFail(err))
    })
  }

  get<T>(url: string, params?: object, config?: HttpRequestConfig): Promise<T> {
    return this.service.get(url, { params, ...config })
  }

  post<T>(url: string, data?: object, config?: HttpRequestConfig): Promise<T> {
    return this.service.post(url, data, config)
  }

  put<T>(url: string, data?: object, config?: HttpRequestConfig): Promise<T> {
    return this.service.put(url, data, config)
  }

  delete<T>(url: string, data?: object, config?: HttpRequestConfig): Promise<T> {
    return this.service.delete(url, data, config)
  }

  upload<T>(url: string, config?: HttpRequestConfig): Promise<T> {
    return this.service.upload(url, config)
  }

  download<T>(url: string, config?: HttpRequestConfig): Promise<T> {
    return this.service.download(url, config)
  }
}

// export interface Result {
//   code: number
//   message: string
//   success?: boolean
// }

// export interface ResultData<T = any> extends Result {
//   data: T
// }

export default BaseRequest
